//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
#include "AP_Cluster.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <iostream>
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
using namespace std;
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
Sim_Cluster::Sim_Cluster():x(0), 
                           y(0), 
                           similarity(0) {};
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
Sim_Cluster::Sim_Cluster(int X, int Y, double Similarity):x(X), 
                                                          y(Y), 
                                                          similarity(Similarity) {};
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
Sim_Cluster::Sim_Cluster(const Sim_Cluster& sim_Cluster): x(sim_Cluster.x), 
                                                          y(sim_Cluster.y), 
                                                          similarity(sim_Cluster.similarity) {};
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
Sim_Cluster::Sim_Cluster(const Sim_Cluster* sim_Cluster): x(sim_Cluster->x), 
                                                          y(sim_Cluster->y), 
                                                          similarity(sim_Cluster->similarity) {};
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
Sim_Cluster::~Sim_Cluster() {};
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
void Sim_Cluster::X(int x) { 
  if (x > 0) this->x = x; 
};
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
void Sim_Cluster::Y(int y) { 
  if (y > 0) this->y = y; 
};
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
void Sim_Cluster::Similarity(double similarity) { 
  this->similarity = similarity; 
};
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
int Sim_Cluster::X(void) { 
  return this->x; 
};
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
int Sim_Cluster::Y(void) { 
  return this->y; 
};
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
double Sim_Cluster::Similarity(void) { 
  return this->similarity; 
};
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
Sim_Cluster Sim_Cluster::operator=(const Sim_Cluster& sim_Cluster) { 
  this->x           = sim_Cluster.x; 
  this->y           = sim_Cluster.y; 
  this->similarity  = sim_Cluster.similarity; 
  return *this; 
};
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
AP_Cluster::AP_Cluster():dataPoints(NULL), 
                         numberDataPoints(0), 
                         preferencePoint(NULL), 
                         idx(NULL), 
                         numberCluster(0), 
                         maxits(1000),
                         convits(100), 
                         dampfact(0.5), 
                         noise(false), 
                         cicle(0) {}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
AP_Cluster::AP_Cluster(const AP_Cluster *aP_Cluster):cicle(0) {

  this->numberDataPoints 	= aP_Cluster->numberDataPoints;
  this->numberCluster 		= aP_Cluster->numberCluster;

  if (this->dataPoints) delete[] this->dataPoints;
  this->dataPoints = new Sim_Cluster[this->numberDataPoints];
  for (int i = 0; i < this->numberDataPoints; i++) 
    this->dataPoints[i] = aP_Cluster->dataPoints[i];

  if (this->preferencePoint) delete[] this->preferencePoint;
  this->preferencePoint = new double[this->numberDataPoints];
  for (int i = 0; i < this->numberDataPoints; i++) 
    this->preferencePoint[i] = aP_Cluster->preferencePoint[i];

  if (this->idx) delete[] this->idx;
  this->idx = new int[this->numberDataPoints];
  for (int i = 0; i < this->numberDataPoints; i++) 
    this->idx[i] = aP_Cluster->idx[i];

  this->maxits    = aP_Cluster->maxits;
  this->convits   = aP_Cluster->convits;
  this->dampfact  = aP_Cluster->dampfact;
  this->noise     = aP_Cluster->noise;

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
AP_Cluster::~AP_Cluster() { 

  if (this->dataPoints)     	delete[] this->dataPoints;
  if (this->preferencePoint) 	delete[] this->preferencePoint;
  if (this->idx)              delete[] this->idx;

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
void AP_Cluster::DataPoints(Sim_Cluster *sim_Cluster, int size) {

  this->numberDataPoints 	= size;

  if (this->dataPoints) delete[] this->dataPoints;
  this->dataPoints = new Sim_Cluster[this->numberDataPoints];
  for (int i = 0; i < this->numberDataPoints; i++) 
    this->dataPoints[i] = sim_Cluster[i];

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
void AP_Cluster::NumberDataPoints(int numberDataPoints) {

  this->numberDataPoints = numberDataPoints;

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
void AP_Cluster::PreferencePoint(double *preferencePoint, int size) {

  this->numberDataPoints 	= size;

  if (this->preferencePoint) delete[] this->preferencePoint;
  this->preferencePoint = new double[this->numberDataPoints];
  for (int i = 0; i < this->numberDataPoints; i++) 
    this->preferencePoint[i] = preferencePoint[i];

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
void AP_Cluster::OnePreference(bool onePreference) {

  this->onePreference = onePreference;

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
void AP_Cluster::Idx(int *idx, int size) {

  this->numberDataPoints 	= size;

  if (this->idx) delete[] this->idx;
  this->idx = new int[this->numberDataPoints];
  for (int i = 0; i < this->numberDataPoints; i++) 
    this->idx[i] = idx[i];

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
void AP_Cluster::NumberCluster(int numberCluster) {

  this->numberCluster = numberCluster;

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
void AP_Cluster::Maxits(int maxits) {

  this->maxits = maxits;

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
void AP_Cluster::Convits(int convits) {

  this->convits = convits;

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
void AP_Cluster::Dampfact(double dampfact) {

  this->dampfact  = dampfact;

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
void AP_Cluster::Noise(bool noise) {

  this->noise	= noise;

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
Sim_Cluster* AP_Cluster::DataPoints(int position) {

  if (position > this->numberDataPoints) return NULL;
  return this->dataPoints[position];

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
int AP_Cluster::NumberDataPoints(void) {

  return this->numberDataPoints;

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
double AP_Cluster::PreferencePoint(int position) {

  if (position > this->numberDataPoints) return 0;
  return this->preferencePoint[position];

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
bool AP_Cluster::OnePreference(void) {

  return this->onePreference;

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
int AP_Cluster::Idx(int position) {

  if (position > this->numberDataPoints) return 0;
  return this->idx[position];

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
int AP_Cluster::NumberCluster(void) {

  return this->numberCluster;

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
int AP_Cluster::Maxits(void) {

  return this->maxits;

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
int AP_Cluster::Convits(void) {

  return this->convits;

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
double AP_Cluster::Dampfact(void) {

  return this->dampfact;

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
bool AP_Cluster::Noise(void) {

  return this->noise;

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
void AP_Cluster::ComputeAP_Cluster(int block) {

    char commandLine[1000];
    CreateSimilarityFile();

    char simMatrix[100];
    sprintf(simMatrix, "./apcluster SimilarityMatrixN%d_AP%7d.txt ", block, this->cicle);
    strcpy(commandLine, simMatrix);

    if (!OnePreference) {
        CreatePreferenceFile();
        char prefMatrix[100];
        sprintf(prefMatrix, "PreferenceN%d_AP%7d.txt ", block, this->cicle);
        strcat(commandLine, prefMatrix);
    }
    else {
        char prefMatrix[100];
        sprintf(prefMatrix, "%f", *(this->preferencePoint));
        strcat(commandLine, prefMatrix);
    }

    char outIDX[100];
    sprintf(outIDX, "IDXResultN%d");

    strcat(commandLine, "\0");
    
    system(commandLine);

    this->cicle++;

}
//---------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------
